package com.fan.gofast.util;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;

@Slf4j
public class ExcelUtils {

    private static final int MAX_ROWS = 1000000;

    private static final String SHEET_NAME = "sheet";

    /**
     * 导出 - 指定sheet名称
     *
     * @param response
     * @param data 查询结果
     * @param fileName 导出文件名称
     * @param sheetName
     * @param clazz 映射实体class类
     * @throws Exception
     */
    public static void writeExcel(HttpServletResponse response, List<? extends Object> data,
                                  String fileName, String sheetName, Class clazz) throws Exception {
        EasyExcel.write(getOutputStream(fileName, response), clazz)
                .excelType(ExcelTypeEnum.XLSX)
                .sheet(sheetName)
                .registerWriteHandler(getDefaultHorizontalCellStyleStrategy()).doWrite(data);
    }

    /**
     * 导出 - 默认sheet名称
     *
     * @param response
     * @param data     查询结果
     * @param fileName 导出文件名称
     * @param clazz    映射实体class类
     * @param <T>      查询结果类型
     * @throws Exception
     */
    public static <T> void writeExcel(HttpServletResponse response, List<T> data,
                                      String fileName, Class clazz) throws Exception {
        // 分割的集合
        List<List<T>> lists = SplitUtils.splitList(data, MAX_ROWS);
        OutputStream out = getOutputStream(fileName, response);
        ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(out, clazz)
                .excelType(ExcelTypeEnum.XLSX)
                .registerWriteHandler(getDefaultHorizontalCellStyleStrategy());
        ExcelWriter excelWriter = excelWriterBuilder.build();
        ExcelWriterSheetBuilder excelWriterSheetBuilder;
        WriteSheet writeSheet;
        for (int i = 1; i <= lists.size(); i++) {
            excelWriterSheetBuilder = new ExcelWriterSheetBuilder(excelWriter);
            excelWriterSheetBuilder.sheetNo(i);
            excelWriterSheetBuilder.sheetName(SHEET_NAME + i);
            writeSheet = excelWriterSheetBuilder.build();
            excelWriter.write(lists.get(i - 1), writeSheet);
        }
        out.flush();
        excelWriter.finish();
        out.close();
    }
    
    public static void main(String[] args) {
    	File testFile = new File("C:/tmp/1222222/a.txt");
    	File fileParent = testFile.getParentFile();//返回的是File类型,可以调用exsit()等方法
    	if (!fileParent.exists()) {
            fileParent.mkdirs();// 能创建多级目录
    	}
	}

    /**
     * 使用模型表头，写excel文件
     *
     * @param path     存储的路径
     * @param
     */
    public static <T> void writeExcel(String path, List<T> data, Class clazz) throws Exception {
    	File file = new File(path);
    	File fileParent = file.getParentFile();//返回的是File类型,可以调用exsit()等方法
    	if (!fileParent.exists()) {
            fileParent.mkdirs();// 能创建多级目录
    	}
        OutputStream out = null;
        out = new FileOutputStream(path);
        try {
            List<List<T>> lists = SplitUtils.splitList(data, MAX_ROWS);
            ExcelWriterBuilder excelWriterBuilder = EasyExcel.write(out, clazz)
                    .excelType(ExcelTypeEnum.XLSX)
                    .registerWriteHandler(getDefaultHorizontalCellStyleStrategy());
            ExcelWriter excelWriter = excelWriterBuilder.build();
            ExcelWriterSheetBuilder excelWriterSheetBuilder;
            WriteSheet writeSheet;
            for (int i = 1; i <= lists.size(); i++) {
                excelWriterSheetBuilder = EasyExcel.writerSheet();
                excelWriterSheetBuilder.sheetNo(i);
                excelWriterSheetBuilder.sheetName(SHEET_NAME + i);
                writeSheet = excelWriterSheetBuilder.build();
                excelWriter.write(lists.get(i - 1), writeSheet);
            }
            out.flush();
            excelWriter.finish();
        } catch (Exception e) {
            log.error("writeExcel error", e);
        } finally {
            out.close();
        }

    }

    /**
     * 获取默认表头内容的样式
     *
     * @return
     */
    private static HorizontalCellStyleStrategy getDefaultHorizontalCellStyleStrategy() {
        /** 表头样式 **/
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 背景色（浅灰色）
        // 可以参考：https://www.cnblogs.com/vofill/p/11230387.html
        headWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        // 字体大小
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 10);
        headWriteCellStyle.setWriteFont(headWriteFont);
        //设置表头居中对齐
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        /** 内容样式 **/
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
        // 内容字体样式（名称、大小）
        WriteFont contentWriteFont = new WriteFont();
        contentWriteFont.setFontName("宋体");
        contentWriteFont.setFontHeightInPoints((short) 10);
        contentWriteCellStyle.setWriteFont(contentWriteFont);
        //设置内容垂直居中对齐
        contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        //设置内容水平居中对齐
        contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        //设置边框样式
        contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);
        contentWriteCellStyle.setBorderTop(BorderStyle.THIN);
        contentWriteCellStyle.setBorderRight(BorderStyle.THIN);
        contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);
        // 头样式与内容样式合并
        return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);
    }

    /**
     *
     * @param fileName
     * @param response
     * @return
     * @throws Exception
     */
    private static OutputStream getOutputStream(String fileName, HttpServletResponse response) throws Exception {
        fileName = URLEncoder.encode(fileName, "UTF-8");
        //  .xls  -- application/vnd.ms-excel
        // .xlsx -- application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
        return response.getOutputStream();
    }
}
